home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / lib / perl5 / File / Find.pm < prev   
Text File  |  1995-07-02  |  5KB  |  225 lines

  1. package File::Find;
  2. require 5.000;
  3. require Exporter;
  4.  
  5. @ISA = qw(Exporter);
  6. @EXPORT = qw(find finddepth);
  7.  
  8. # Usage:
  9. #    use File::Find;
  10. #
  11. #    find(\&wanted, '/foo','/bar');
  12. #
  13. #    sub wanted { ... }
  14. #        where wanted does whatever you want.  $dir contains the
  15. #        current directory name, and $_ the current filename within
  16. #        that directory.  $name contains "$dir/$_".  You are cd'ed
  17. #        to $dir when the function is called.  The function may
  18. #        set $prune to prune the tree.
  19. #
  20. # This library is primarily for find2perl, which, when fed
  21. #
  22. #   find2perl / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune
  23. #
  24. # spits out something like this
  25. #
  26. #    sub wanted {
  27. #        /^\.nfs.*$/ &&
  28. #        (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  29. #        int(-M _) > 7 &&
  30. #        unlink($_)
  31. #        ||
  32. #        ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) &&
  33. #        $dev < 0 &&
  34. #        ($prune = 1);
  35. #    }
  36. #
  37. # Set the variable $dont_use_nlink if you're using AFS, since AFS cheats.
  38.  
  39. sub find {
  40.     my $wanted = shift;
  41.     chop($cwd = `pwd`);
  42.     foreach $topdir (@_) {
  43.     (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
  44.       || (warn("Can't stat $topdir: $!\n"), next);
  45.     if (-d _) {
  46.         if (chdir($topdir)) {
  47.         ($dir,$_) = ($topdir,'.');
  48.         $name = $topdir;
  49.         &$wanted;
  50.         ($fixtopdir = $topdir) =~ s,/$,, ;
  51.         &finddir($wanted,$fixtopdir,$topnlink);
  52.         }
  53.         else {
  54.         warn "Can't cd to $topdir: $!\n";
  55.         }
  56.     }
  57.     else {
  58.         unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) {
  59.         ($dir,$_) = ('.', $topdir);
  60.         }
  61.         $name = $topdir;
  62.         chdir $dir && &$wanted;
  63.     }
  64.     chdir $cwd;
  65.     }
  66. }
  67.  
  68. sub finddir {
  69.     local($wanted,$dir,$nlink) = @_;
  70.     local($dev,$ino,$mode,$subcount);
  71.     local($name);
  72.  
  73.     # Get the list of files in the current directory.
  74.  
  75.     opendir(DIR,'.') || (warn "Can't open $dir: $!\n", return);
  76.     local(@filenames) = readdir(DIR);
  77.     closedir(DIR);
  78.  
  79.     if ($nlink == 2 && !$dont_use_nlink) {  # This dir has no subdirectories.
  80.     for (@filenames) {
  81.         next if $_ eq '.';
  82.         next if $_ eq '..';
  83.         $name = "$dir/$_";
  84.         $nlink = 0;
  85.         &$wanted;
  86.     }
  87.     }
  88.     else {                    # This dir has subdirectories.
  89.     $subcount = $nlink - 2;
  90.     for (@filenames) {
  91.         next if $_ eq '.';
  92.         next if $_ eq '..';
  93.         $nlink = $prune = 0;
  94.         $name = "$dir/$_";
  95.         &$wanted;
  96.         if ($subcount > 0 || $dont_use_nlink) {    # Seen all the subdirs?
  97.  
  98.         # Get link count and check for directoriness.
  99.  
  100.         ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink;
  101.         
  102.         if (-d _) {
  103.  
  104.             # It really is a directory, so do it recursively.
  105.  
  106.             if (!$prune && chdir $_) {
  107.             &finddir($wanted,$name,$nlink);
  108.             chdir '..';
  109.             }
  110.             --$subcount;
  111.         }
  112.         }
  113.     }
  114.     }
  115. }
  116.  
  117. # Usage:
  118. #    use File::Find;
  119. #
  120. #    finddepth(\&wanted, '/foo','/bar');
  121. #
  122. #    sub wanted { ... }
  123. #        where wanted does whatever you want.  $dir contains the
  124. #        current directory name, and $_ the current filename within
  125. #        that directory.  $name contains "$dir/$_".  You are cd'ed
  126. #        to $dir when the function is called.  The function may
  127. #        set $prune to prune the tree.
  128. #
  129. # This library is primarily for find2perl, which, when fed
  130. #
  131. #   find2perl / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune
  132. #
  133. # spits out something like this
  134. #
  135. #    sub wanted {
  136. #        /^\.nfs.*$/ &&
  137. #        (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  138. #        int(-M _) > 7 &&
  139. #        unlink($_)
  140. #        ||
  141. #        ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) &&
  142. #        $dev < 0 &&
  143. #        ($prune = 1);
  144. #    }
  145.  
  146. sub finddepth {
  147.     my $wanted = shift;
  148.     chop($cwd = `pwd`);
  149.     foreach $topdir (@_) {
  150.     (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
  151.       || (warn("Can't stat $topdir: $!\n"), next);
  152.     if (-d _) {
  153.         if (chdir($topdir)) {
  154.         ($fixtopdir = $topdir) =~ s,/$,, ;
  155.         &finddepthdir($wanted,$fixtopdir,$topnlink);
  156.         ($dir,$_) = ($fixtopdir,'.');
  157.         $name = $fixtopdir;
  158.         &$wanted;
  159.         }
  160.         else {
  161.         warn "Can't cd to $topdir: $!\n";
  162.         }
  163.     }
  164.     else {
  165.         unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) {
  166.         ($dir,$_) = ('.', $topdir);
  167.         }
  168.         chdir $dir && &$wanted;
  169.     }
  170.     chdir $cwd;
  171.     }
  172. }
  173.  
  174. sub finddepthdir {
  175.     my($wanted,$dir,$nlink) = @_;
  176.     my($dev,$ino,$mode,$subcount);
  177.     my($name);
  178.  
  179.     # Get the list of files in the current directory.
  180.  
  181.     opendir(DIR,'.') || warn "Can't open $dir: $!\n";
  182.     my(@filenames) = readdir(DIR);
  183.     closedir(DIR);
  184.  
  185.     if ($nlink == 2) {        # This dir has no subdirectories.
  186.     for (@filenames) {
  187.         next if $_ eq '.';
  188.         next if $_ eq '..';
  189.         $name = "$dir/$_";
  190.         $nlink = 0;
  191.         &$wanted;
  192.     }
  193.     }
  194.     else {                    # This dir has subdirectories.
  195.     $subcount = $nlink - 2;
  196.     for (@filenames) {
  197.         next if $_ eq '.';
  198.         next if $_ eq '..';
  199.         $nlink = $prune = 0;
  200.         $name = "$dir/$_";
  201.         if ($subcount > 0) {    # Seen all the subdirs?
  202.  
  203.         # Get link count and check for directoriness.
  204.  
  205.         ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink;
  206.         
  207.         if (-d _) {
  208.  
  209.             # It really is a directory, so do it recursively.
  210.  
  211.             if (!$prune && chdir $_) {
  212.             &finddepthdir($wanted,$name,$nlink);
  213.             chdir '..';
  214.             }
  215.             --$subcount;
  216.         }
  217.         }
  218.         &$wanted;
  219.     }
  220.     }
  221. }
  222.  
  223. 1;
  224.  
  225.